<?

//require_once(dirname(__FILE__) . '/../abstract/db.php');

abstract class bf_db_pdo extends bf_db {

	protected $conn;
	private $params;

	public function __construct($options = array()) {
		$def_opts = $this->default_options();
		$opts = array_merge($def_opts, $options);
		parent::__construct($opts);
	}

	protected abstract function default_options();
	protected abstract function data_source_name();

	public function escape($str) {
		return $this->conn->quote($str);
	}

	public function connect() {
		try {
			$this->conn = new PDO($this->data_source_name());
		} catch (Exception $e) {
			$this->conn = null;
		}
		if (!$this->conn) {
			$this->log_append("Couldn't connect to database {$this->opts['database']}");
		}
	}

	public function disconnect() {
		if ($this->conn) {
			$this->conn = null;
		}
	}

	public function is_connected() {
		return ($this->conn ? true : false);
	}

	protected function make_query($sql, $params = array()) {
		$this->params = $params;
		$processed_sql = preg_replace_callback("/'(?:\\'|.)*?'|\\$(\\d+)/", array($this, 'get_param'), $sql);
		$this->params = null;
		if ($this->opts['logging'] > 1)
			$this->log_append("SQL: $sql\nPARAMS: ".join(', ', $params)."\nSQL TO EXECUTE: $processed_sql\n");
		if (!($res = @$this->conn->query($processed_sql)))
			$this->log_error();
		return $res;
	}

	public function fetch_all($res, $params = array()) {
		$rows = array();
		while ($row = $this->fetch_row($res)) {
			$rows[] = $row;
		}
		return $rows;
	}

	public function fetch_row($res) {
		if ($res) {
			return @$res->fetch(PDO::FETCH_ASSOC);
		}
		return null;
	}

	public function fetch_column($res, $column = false) {
		if ($res) {
			$row = $this->fetch_row($res);
			if ($row) {
				foreach ($row as $k => $v) {
					if ($column) {
						if ($column == $k) {
							return $v;
						}
					} else {
						return $v;
					}
				}
			}
		}
		return null;
	}

	public function is_error() {
		return ($this->get_error_text() ? true : false);
	}

	public function get_error_text() {
		if ($this->conn) {
			$info = $this->conn->errorInfo();
			return @$info[2];
		}
		return "Couldn't connect to database.";
	}

	public function get_debug_text() {
		return '';
	}

	public function start() {
		return $this->conn->beginTransaction();
	}

	public function commit() {
		return $this->conn->commit();
	}

	public function rollback() {
		return $this->conn->rollBack();
	}

	private function get_param($matches) {
		if (preg_match('/^\$/', $matches[0])) {
			$param = $this->params[intval($matches[1]) - 1];
			if ($param === null) {
				return 'NULL';
			}
			if (is_int($param)) {
				return $param;
			}
			return $this->escape($param);
		} else {
			return $matches[0];
		}
	}
}

?>